import type { RouteRecordRaw, RouteMeta } from "vue-router";
import type { DefineComponent } from "vue";
import { ROUTE_MODULE_LEVEL } from "./const";
import { APP_ROUTER_META_DEFAULT_CONFIG } from "@/config";
/** 获取路由权限key入参 */
export interface GetRoutePermissionParams {
  /** 路由路径 */
  path: string;
  /** 权限配置 */
  permission: RouteMeta["permission"];
}

/** 获取路由权限key */
export const getRoutePermissionKey = ({
  path,
  permission: permissionConfig,
}: GetRoutePermissionParams) => {
  if (!permissionConfig) {
    return;
  }
  const { key, keyUsePath } = permissionConfig;

  if (key) {
    return key;
  } else if (keyUsePath) {
    return path;
  }
};

/** 路由元信息解析raw */
export interface RouteMetaResolveRaw {
  /** 路由地址 */
  path: string;
  /** 页面名称 */
  title: string;
  /** 路由级别 */
  routeLevel: number;
  /**
   * 是否重定向到第一个有权限的子路由
   * 详见 RouteMeta.redirectToFirstChildRoute
   */
  redirectToFirstChildRoute: boolean;
  /** 是否在菜单展示 */
  menuShow: boolean;
  /** 菜单icon */
  menuIcon?: DefineComponent;
  /** 菜单排序 */
  menuSort: number;
  /** 子路由原始配置 */
  childrenRaw: RouteRecordRaw[];
  /** 子路由元信息解析raw */
  children: RouteMetaResolveRaw[];
  /** 父路由地址 */
  parentPath: string;
  /** 父路由地址列表 */
  parentPathList: string[];
  /** 权限key */
  permissionKey?: string | number;
  /** 是否检测权限 */
  checkPermission: boolean;
  /** (配置权限的前提下)权限编辑时是否展示 */
  permissionEditShow: boolean;
  /** 是否需要登录 */
  needLogin: boolean;
}

/** 从routes生成路由元信息解析raw */
export const generateRouteMetaRawTree = <
  T extends {
    children: T[];
  } = RouteMetaResolveRaw,
>(
  routesList: RouteRecordRaw[],
  {
    parentPath = "",
    parentPathList = [],
    routeLevel = ROUTE_MODULE_LEVEL,
    sortFn,
    mapFn,
    filterFn,
  }: Partial<
    Pick<
      RouteMetaResolveRaw,
      "parentPath" | "parentPathList" | "routeLevel"
    > & {
      /** 排序函数 */
      sortFn?: (a: T, b: T) => number;
      /** 映射函数 */
      mapFn: (
        route: Omit<RouteMetaResolveRaw, "children"> & {
          children: T[];
        },
      ) => T;
      /** 过滤函数 */
      filterFn: (
        raw: Omit<RouteMetaResolveRaw, "children"> & {
          children: T[];
        },
        /** 是否有符合过滤条件的子路由 */
        haveChildren: boolean,
        /** [原始配置]是否有子路由 */
        haveChildrenRaw: boolean,
      ) => boolean;
    }
  > = {},
): T[] => {
  // console.log("routes", routesList);
  const list: T[] = [];
  routesList.forEach((route) => {
    const { path, children, meta } = route;
    if (!meta) {
      console.error(`路由${path}未配置meta`);
      return;
    }
    const { menu, redirectToFirstChildRoute = true } = meta;

    const { title, permission } = meta;
    const currentPath = path.startsWith("/") ? path : `${parentPath}/${path}`;
    const currentPathList = [...parentPathList, currentPath];

    const permissionKey = getRoutePermissionKey({
      path: currentPath,
      permission,
    });

    const metaResolveRaw: Omit<RouteMetaResolveRaw, "children"> & {
      children: T[];
    } = {
      path: currentPath,
      title,
      routeLevel,
      redirectToFirstChildRoute,
      menuShow: menu?.show ?? APP_ROUTER_META_DEFAULT_CONFIG.menuShow,
      menuIcon: menu?.icon,
      menuSort: menu?.sort || 0,
      childrenRaw: Array.isArray(children) ? children : [],
      children: children
        ? generateRouteMetaRawTree(children, {
            parentPath: currentPath,
            parentPathList: currentPathList,
            routeLevel: routeLevel + 1,
            filterFn,
            mapFn,
            sortFn,
          })
        : [],
      parentPath,
      parentPathList,
      permissionKey,
      checkPermission: !!permissionKey,
      permissionEditShow: permissionKey ? permission?.editShow ?? true : false,
      needLogin: permission?.login ?? APP_ROUTER_META_DEFAULT_CONFIG.needLogin,
    };

    // console.log(`
    //   ${currentPath}
    //   父路由地址列表: ${parentPathList}
    //   ${permissionKey ? "需要" : "不需要"}检测权限
    //   ${permissionKey ? `${permissionKey}` : ""}
    //   hasChildren: ${metaResolveRaw.children.length > 0}

    // `);
    if (
      filterFn &&
      !filterFn(
        metaResolveRaw,
        metaResolveRaw.children.length > 0,
        metaResolveRaw.childrenRaw.length > 0,
      )
    ) {
      return;
    }

    const res: T = mapFn
      ? mapFn(metaResolveRaw)
      : (metaResolveRaw as unknown as T);

    list.push(res);
  });
  sortFn && list.sort(sortFn);
  return list;
};

/** 扁平化路由元信息解析raw */
export const flatRouteMetaResolveRaw = <
  T extends {
    children: T[];
  },
>(
  list: T[],
  arr: T[] = [],
) => {
  list.forEach((item) => {
    arr.push(item);
    flatRouteMetaResolveRaw(item.children, arr);
  });

  return arr;
};
